
//condition: the minimum frame size is 8.
//focus on: data=>remain,pre_mod=>sop,eop,mod
`include "defines.v"

module hdlc_framer(
		//input
		clk,
		rst,
		
		ready,
		snk_ready,
		abort,
		sop_ind,
		eop_ind,
		data,
		
		//output
		drd,		
		snk_val,
		snk_sop,
		snk_eop,
		snk_err,
		snk_mod,
		snk_data
);

//pin
input					clk;
input					rst;
input					ready;
input					snk_ready;
input	[15:0]	abort/* synthesis syn_keep = 1 */;
input	[15:0]	sop_ind/* synthesis syn_keep = 1 */;
input	[15:0]	eop_ind/* synthesis syn_keep = 1 */;
input	[127:0]	data;

output				drd;
output				snk_val;
output				snk_sop;
output				snk_eop;
output				snk_err;
output[3:0]		snk_mod;
output[127:0]	snk_data;

////////// CODE ///////////////////////////////////////////
//reg
reg						hold;
reg						hold_delay;
reg						hold_d1;
reg						hold_delay_d1;
reg						ready_d1;
reg						hold_delay_d2;

reg	[15:0]		discard/* synthesis syn_keep = 1 */;
reg	[15:0]		discard_d1;
reg	[15:0]		discard_d2;
reg						pre_err;

reg	[15:0]		pre_remain;
reg	[15:0]		eop_rec;

reg	[15:0]		sop;
reg	[15:0]		eop;
reg	[3:0]			sop_pos;
reg	[3:0]			eop_pos;
reg	[4:0]			offset;
reg	[4:0]			offset_eop;
reg	[4:0]			offset_eop_d1;

reg	[15:0]		sop_d1;
reg	[15:0]		eop_d1;
reg						sop_d2;
reg						eop_d2;

reg						double_sop;
reg						double_eop;
reg						sop_eop;
reg						no_sop;
reg						no_eop;
reg						sop_full;
reg						sop_full_d1;
reg						jump;

reg	[127:0]		din_d1;
reg	[127:0]		din_d2;
reg	[127:0]		sopData;
reg	[255:0]		dD1;

reg						drd_d1;
reg						drd_d2;
reg						dval;
reg						dval_d1;
reg						overflow;
reg						overflow_d1;
reg						overflow_d2;
reg						overflow_d3;
reg						sop_hold;
reg						sop_hold_d1;

reg	[4:0]			remain;
reg	[4:0]			pre_mod;
reg						start;
reg						val;
reg						snk_val/* synthesis syn_keep = 1 */;
reg						snk_sop/* synthesis syn_keep = 1 */;
reg						snk_eop/* synthesis syn_keep = 1 */;
reg						snk_err/* synthesis syn_keep = 1 */;
reg	[3:0]			snk_mod/* synthesis syn_keep = 1 */;
reg	[127:0]		snk_data/* synthesis syn_keep = 1 */;

//wire
wire[127:0]		din/* synthesis syn_keep = 1 */;
wire					drd/* synthesis syn_keep = 1 */;
wire	[4:0]		remainT;

////////// code ////////////////////
assign din = data;

//pre
assign drd = (ready&snk_ready&hold&hold_delay);//(ready&snk_ready&(~nxt_state[0]));//snk_ready

//pre_remain, to generate overflow.
//only when sop and eop are not together, overflow will occur.
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			pre_remain <= 16'h0;
		else if(sop_ind==16'h8000 && drd_d1==1'h1)// && eop_ind<16'h0002)
			pre_remain <= 16'h0;
		else if(sop_ind[15:8]>8'h0 && sop_ind[7:0]>8'h0 && drd_d1==1'h1)//two sop
			pre_remain <= {8'h0,sop_ind[7:0]};
		else if(sop_ind>16'h0 && (eop_ind>sop_ind || eop_ind==16'h0) && drd_d1==1'h1)//only sop.
			pre_remain <= sop_ind;
end

//hold
always @(*)
begin
		if(eop_ind[15:8]>8'h0 && eop_ind[7:0]>8'h0 && drd_d1==1'h1)//two eop, eop_sop_eop,one hold cycle
			hold = 1'h0;
		else if(eop_ind>sop_ind && eop_ind<=pre_remain && drd_d1==1'h1)//only one eop or sop, so when eop>sop,overflow
			hold = 1'h0;
		else
			hold = 1'h1;
end

//hold_delay
always @(posedge clk or `RST_EDGE rst)//modify, eop_sop_eop_sop
begin
		if(rst == `RST_VALUE)
			hold_delay <= 1'h1; 
		else if(eop_ind>sop_ind && eop_ind[15:8]>8'h0 && eop_ind[7:0]>8'h0 && eop_ind[15:8]<=pre_remain[15:8] && drd_d1==1'h1)//one or two sop and two eop, overflow//
			hold_delay <= 1'h0;
		else
			hold_delay <= 1'h1;
end
///////////// pre end /////////////////

//first
//delay
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
		begin
			din_d1 <= 128'h0;
			din_d2 <= 128'h0;
			discard_d1 <= 16'h0;
			discard_d2 <= 16'h0;
			sop_d1 <= 16'h0;
    	eop_d1 <= 16'h0;    
    	ready_d1 <= 1'h0;    	
    	drd_d1 <= 1'h0;
    	drd_d2 <= 1'h0;
    	hold_d1 <= 1'h1;
    	overflow_d1 <= 1'h0;
    	overflow_d2 <= 1'h0;
    	overflow_d3 <= 1'h0;
    	sop_hold_d1 <= 1'h0;
    	hold_delay_d1 <= 1'h0;
    	hold_delay_d2 <= 1'h0;
    	sop_full_d1 <= 1'h0;
    	offset_eop_d1 <= 5'h0;
		end
		else
		begin
			din_d1 <= din;
			din_d2 <= din_d1;//
			discard_d1 <= discard;
			discard_d2 <= discard_d1;
			sop_d1 <= sop;
    	eop_d1 <= eop;    	
    	ready_d1 <= ready;
    	drd_d1 <= drd;
    	drd_d2 <= drd_d1;
    	hold_d1 <= hold;
    	overflow_d1 <= overflow;
    	overflow_d2 <= overflow_d1;
    	overflow_d3 <= overflow_d2;
    	sop_hold_d1 <= sop_hold;
    	hold_delay_d1 <= hold_delay;
    	hold_delay_d2 <= hold_delay_d1;
    	sop_full_d1 <= sop_full;
    	offset_eop_d1 <= offset_eop;
		end
end

//the remainder data add the data of eop will exceed word(16 bytes).//
//Then eop will be delay by one cycle.
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			overflow <= 1'h0;
		else if(eop_ind[7:0]>8'h0 && eop_ind[15:8]>8'h0 && ({eop_ind[15:8],8'h0}<=pre_remain) && eop_ind>sop_ind && drd_d1==1'h1)//two eop, overflow,
			overflow <= 1'h1;
		else if(eop_ind>16'h0 && eop_ind<=pre_remain && eop_ind>sop_ind && drd_d1==1'h1)//only one eop, overflow,
			overflow <= 1'h1;
		else
			overflow <= 1'h0;
end

//sop
always @(posedge clk or `RST_EDGE rst)//sop_eop,eop move with sop;
begin
		if(rst == `RST_VALUE)
    	sop <= 16'h0;
    else if(drd_d1==1'h1)		//process in time
    	sop <= sop_ind;
    else if(ready_d1==1'h0 && hold_d1==1'h1 && hold_delay_d1==1'h1)
    	sop <= 16'h0;
    else if(hold_delay_d1==1'h0)
    	sop <= sop;
    else if((eop>sop && sop>16'h0)|| (overflow_d1==1'h1 && eop>16'h0)) //1-eop>sop,2-when overflow, sop hold,eop_sop_eop, eop_sop or eop_sop_eop_sop
    	sop <= sop;
    else if(sop[7:0]>16'h0 && sop[15:8]>16'h0)//two sop, and sop_eop
    	sop <= {8'h0,sop[7:0]};  
    else
    	sop <= 16'h0;
end

//eop
always @(posedge clk or `RST_EDGE rst)//sop_eop,eop move with sop;
begin//notice: data+eop exceed 16 bytes.
		if(rst == `RST_VALUE)
    	eop <= 16'h0;
    else if(drd_d1==1'h1)		//process in time
    	eop <= eop_ind;
    else if(ready_d1==1'h0 && hold_d1==1'h1 && hold_delay_d1==1'h1)
    	eop <= 16'h0;
    else if(hold_delay_d1==1'h0)
    	eop <= eop;
    else if(eop[15:8]>8'h0 && eop[7:0]>8'h0)// || (overflow==1'h1 && eop[7:0]>8'h0))//two eop, the upper eop is priority.
    	eop <= {8'h0,eop[7:0]};
    else
    	eop <= 16'h0;
end

//discard, the same as eop
always @(posedge clk or `RST_EDGE rst)//sop_eop,eop move with sop;//modify overflow,error
begin//notice: data+eop exceed 16 bytes.
		if(rst == `RST_VALUE)
    	discard <= 16'h0;
    else if(drd_d1==1'h1)
    	discard <= (abort&eop_ind);
    else if(ready_d1==1'h0 && hold_d1==1'h1 && hold_delay_d1==1'h1)
    	discard <= 16'h0;
    else if(hold_delay_d1==1'h0)
    	discard <= discard;    	
    else if(eop[15:8]>8'h0 && eop[7:0]>8'h0)//two eop, the upper eop is priority.
    	discard <= {8'h0,discard[7:0]};  
    else
    	discard <= 16'h0;
end

//dval
always @(posedge clk or `RST_EDGE rst)//sop_eop,eop move with sop;
begin
		if(rst == `RST_VALUE)
    	dval <= 1'h0;
    else if(sop_ind==16'h0 && eop_ind==16'h0 && drd_d1==1'h1)//data, && init==1'h1
    	dval <= 1'h1;
    else
    	dval <= 1'h0;
end

//dval_d1
always @(posedge clk or `RST_EDGE rst)//sop_eop,eop move with sop;
begin
		if(rst == `RST_VALUE)
    	dval_d1 <= 1'h0;
    else //if(drd_d2==1'h1)// && hold_d1==1'h1)//data
    	dval_d1 <= dval;
end
///////////////// the first end ///////////////////////////////////////

//second
//double_sop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			double_sop <= 1'h0;
		else if(sop[15:8]>8'h0 && sop[7:0]>8'h0)
			double_sop <= 1'h1;
		else
			double_sop <= 1'h0;
end

//double_eop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			double_eop <= 1'h0;
		else if(eop[15:8]>8'h0 && eop[7:0]>8'h0)
			double_eop <= 1'h1;
		else
			double_eop <= 1'h0;
end

//sop_eop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			sop_eop <= 1'h0;
		else if(sop>eop)
			sop_eop <= 1'h1;
		else
			sop_eop <= 1'h0;
end

//no_sop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			no_sop <= 1'h0;
		else if(sop==16'h0)
			no_sop <= 1'h1;
		else
			no_sop <= 1'h0;
end

//no_eop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			no_eop <= 1'h0;
		else if(eop==16'h0)
			no_eop <= 1'h1;
		else
			no_eop <= 1'h0;
end

//sop_full
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			sop_full <= 1'h0;
		else if(sop==16'h8000 && eop==16'h0)
			sop_full <= 1'h1;
		else
			sop_full <= 1'h0;
end

//jump,eop_sop_eop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			jump <= 1'h0;
		else if(eop_d1>sop_d1 && eop_d1[15:8]>8'h0 && eop_d1[7:0]>8'h0)//eop_sop_sop
			jump <= 1'h1;
		else
			jump <= 1'h0;
end

//sop_pos
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			sop_pos <= 4'h0;
		else if(sop[15:8]>0)
		begin
			case(sop[15:8])
			8'h01:		sop_pos <= 4'h8;
			8'h02:		sop_pos <= 4'h9;
			8'h04:		sop_pos <= 4'hA;
			8'h08:		sop_pos <= 4'hB;
			8'h10:		sop_pos <= 4'hC;
			8'h20:		sop_pos <= 4'hD;
			8'h40:		sop_pos <= 4'hE;
			default:	sop_pos <= 4'hF;
			endcase
		end
		else
		begin
			case(sop[7:0])
			8'h01:		sop_pos <= 4'h0;
			8'h02:		sop_pos <= 4'h1;
			8'h04:		sop_pos <= 4'h2;
			8'h08:		sop_pos <= 4'h3;
			8'h10:		sop_pos <= 4'h4;
			8'h20:		sop_pos <= 4'h5;
			8'h40:		sop_pos <= 4'h6;
			default:	sop_pos <= 4'h7;
			endcase
		end
end

//eop_pos
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			eop_pos <= 4'h0;
		else if(eop[15:8]>0)
		begin
			case(eop[15:8])
			8'h01:		eop_pos <= 4'h8;
			8'h02:		eop_pos <= 4'h9;
			8'h04:		eop_pos <= 4'hA;
			8'h08:		eop_pos <= 4'hB;
			8'h10:		eop_pos <= 4'hC;
			8'h20:		eop_pos <= 4'hD;
			8'h40:		eop_pos <= 4'hE;
			default:	eop_pos <= 4'hF;
			endcase
		end
		else
		begin
			case(eop[7:0])
			8'h01:		eop_pos <= 4'h0;
			8'h02:		eop_pos <= 4'h1;
			8'h04:		eop_pos <= 4'h2;
			8'h08:		eop_pos <= 4'h3;
			8'h10:		eop_pos <= 4'h4;
			8'h20:		eop_pos <= 4'h5;
			8'h40:		eop_pos <= 4'h6;
			default:	eop_pos <= 4'h7;
			endcase
		end
end

//offset,sop_eop_sop,eop_sop,sop,
always @(posedge clk or `RST_EDGE rst)
begin	//single sop is no consider.
		if(rst == `RST_VALUE)
			offset <= 5'h0;
		else if((sop[15:8]==8'h0 && sop[7:0]>8'h0) || (sop>eop && sop[15:8]>8'h0 && sop[7:0]>8'h0))//eop_sop, or two sop
		begin
			case(sop[7:0])
			8'h01:		offset <= 5'h1;
			8'h02:		offset <= 5'h2;
			8'h04:		offset <= 5'h3;
			8'h08:		offset <= 5'h4;
			8'h10:		offset <= 5'h5;
			8'h20:		offset <= 5'h6;
			8'h40:		offset <= 5'h7;
			8'h80:		offset <= 5'h8;
			default:	offset <= offset;
			endcase
		end
		else if((sop[7:0]==8'h0) || (eop>sop && sop[15:8]>8'h0 && sop[7:0]>8'h0))//only one sop or eop_sop_eop_sop
		begin
			case(sop[15:8])
			8'h01:		offset <= 5'h9;
			8'h02:		offset <= 5'hA;
			8'h04:		offset <= 5'hB;
			8'h08:		offset <= 5'hC;
			8'h10:		offset <= 5'hD;
			8'h20:		offset <= 5'hE;
			8'h40:		offset <= 5'hF;
			//8'h80:		offset <= 5'h10;
			default:	offset <= offset;
			endcase
		end
		else
			offset <= 5'h0;
end

//offset_eop
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			offset_eop <= 5'h0;
		else if(eop>sop && ((sop[15:8]>8'h0 && sop[7:0]>8'h0) || (eop[15:8]>8'h0 && eop[7:0]>8'h0)))//only one sop or eop_sop_eop_sop
		begin
			case(eop[7:0])
			8'h01:		offset_eop <= 5'h0;
			8'h02:		offset_eop <= 5'h1;
			8'h04:		offset_eop <= 5'h2;
			8'h08:		offset_eop <= 5'h3;
			8'h10:		offset_eop <= 5'h4;
			8'h20:		offset_eop <= 5'h5;
			8'h40:		offset_eop <= 5'h6;
			//8'h80:		offset_eop <= 5'h10;
			default:	offset_eop <= 5'h7;
			endcase
		end
		else
			offset_eop <= 5'h0;
end
////////////////// second end //////////////////////////

//third
//remain
assign remainT = remain - 5'h1;
always @(posedge clk or `RST_EDGE rst)//
begin
		if(rst == `RST_VALUE)
			remain <= 5'h0;
		else if(no_sop==1'h0 && no_eop==1'h1)//only sop, and when no valid, hold on. Need to judge the sop, && double_sop==1'h0 && 
			remain <= {remainT[4],4'h0} + 5'h11 + {1'h0,sop_pos};
		else if(no_sop==1'h1 && no_eop==1'h0)//only eop
			remain <= remain + 5'h10 - {1'h0,eop_pos};
		else if(sop_eop==1'h0 && double_sop==1'h0  && no_sop==1'h0 && double_eop==1'h0)//eop_sop
			remain <= {{~remainT[4]},4'h0} + offset;
		//else if(double_sop==1'h1 && sop_eop==1'h1 && double_eop==1'h0)//sop_eop_sop
		//	remain <= {remainT[4],4'h0} + offset;
		else if(double_sop==1'h1 && sop_eop==1'h1 && double_eop==1'h0)//sop_eop_sop
			remain <= {pre_mod[4],4'h0} + offset;
		//else if(double_sop==1'h1 && sop_eop==1'h0 && double_eop==1'h1)//eop_sop_eop_sop
		//	remain <= {{~remain[4]},4'h0} + offset - offset_eop;
		else if(sop_eop==1'h0 && double_eop==1'h1)//eop_sop_eop_sop
			remain <= {{~remainT[4]},4'h0} + offset;// - offset_eop;
		else if(sop_eop==1'h1 && no_eop==1'h0)//sop_eop
			remain <= {remainT[4],4'h0} + 5'h11 - {1'h0,eop_pos} + {1'h0,sop_pos};
		else if(dval_d1==1'h1 && no_sop==1'h1 && no_eop==1'h1)//only data
			remain <= remain + 5'h10;
end

//pre_mod
always @(posedge clk or `RST_EDGE rst)//the same as sop_d1
begin
		if(rst == `RST_VALUE)
			pre_mod <= 5'h0;
		else if(jump==1'h1)//when overflow and pre_clock address is jump, mod hold on,overflow_d2==1'h1 || 
			pre_mod <= remain - offset_eop_d1;
		else if(double_sop==1'h0 && no_sop==1'h0 && no_eop==1'h1)//only sop,  && remain==pre_mod
			pre_mod <= {remainT[4],4'h0} + 5'h11 + {1'h0,sop_pos};
		//else if(sop_eop==1'h0 && no_eop==1'h0 && double_eop==1'h1)//eop_sop_eop
		//	pre_mod <= remain;
		else if(sop_eop==1'h0 && no_eop==1'h0)//eop_sop,eop over sop, && double_sop==1'h0 && double_eop==1'h0
			pre_mod <= remain + 5'h10 - {1'h0,eop_pos};
		else if(sop_eop==1'h1 && no_eop==1'h0)//sop_eop
			pre_mod <= {remainT[4],4'h0} + 5'h11 - {1'h0,eop_pos} + {1'h0,sop_pos};
		else if(dval_d1==1'h1 && no_sop==1'h1 && no_eop==1'h1)//only data
			pre_mod <= remain + 5'h10;
end
		
//sop hold, sop should be hold till data has been sent out.
always @(posedge clk or `RST_EDGE rst)//modify,overflow
begin
		if(rst == `RST_VALUE)
			sop_hold <= 1'h0;
		else if((sop>16'h0 && sop<16'h8000 && eop==16'h0) || hold_delay_d1==1'h0)//only one sop, sop delay
			sop_hold <= 1'h1;
		//else if(sop_eop==1'h1 && overflow==1'h1)//overflow, because sop and eop is hold when overflow
		//	sop_hold <= 1'h1;
		else if(sop[15:8]>8'h0 && sop[7:0]>8'h0 && sop>eop)//sop_eop_sop
			sop_hold <= 1'h1;
		else if(eop>sop && ((eop[15:8]>8'h0 && eop[7:0]==8'h0) || (eop[15:8]==8'h0 && eop[7:0]>8'h0)))//eop_sop, one eop
			sop_hold <= 1'h1;
		//else if(sop>16'h0 && eop>16'h0 && overflow_d1==1'h1)//after overflow, recorve,//remove, because sop and eop is hold after overflow
		//	sop_hold <= 1'h0;
		else if((sop==16'h0 || eop>sop || sop==16'h8000) && drd_d2==1'h1)//eop or data
			sop_hold <= 1'h0;
end

//val
always @(posedge clk or `RST_EDGE rst)//modify,overflow
begin
		if(rst == `RST_VALUE)
			val <= 1'h0;
		else if(eop_d1>0 || overflow_d2>1'h0)//eop or overflow
			val <= 1'h1;
		else if(sop_d1==16'h8000)//sop
			val <= 1'h1;
		else if(dval_d1==1'h1 && sop_d1==16'h0 && eop_d1==16'h0)//data
			val <= 1'h1;
		else
			val <= 1'h0;
end

//sopData
always @(posedge clk or `RST_EDGE rst)
begin 
		if(rst == `RST_VALUE)
			sopData <= 128'h0;
		else //if(sop_d1>eop_d1)//
		begin
			case(offset)
			5'h01:		sopData <= {din_d2[119:0],din_d2[7:0]  }; 
			5'h02:		sopData <= {din_d2[111:0],din_d2[15:0] };
			5'h03:		sopData <= {din_d2[103:0],din_d2[23:0] };
			5'h04:		sopData <= {din_d2[95:0] ,din_d2[31:0] }; 
			5'h05:		sopData <= {din_d2[87:0] ,din_d2[39:0] }; 
			5'h06:		sopData <= {din_d2[79:0] ,din_d2[47:0] }; 
			5'h07:		sopData <= {din_d2[71:0] ,din_d2[55:0] }; 
			5'h08:		sopData <= {din_d2[63:0] ,din_d2[63:0] }; 
			5'h09:		sopData <= {din_d2[55:0] ,din_d2[71:0] }; 
			5'h0A:		sopData <= {din_d2[47:0] ,din_d2[79:0] }; 
			5'h0B:		sopData <= {din_d2[39:0] ,din_d2[87:0] }; 
			5'h0C:		sopData <= {din_d2[31:0] ,din_d2[95:0] }; 
			5'h0D:		sopData <= {din_d2[23:0] ,din_d2[103:0]};
			5'h0E:		sopData <= {din_d2[15:0] ,din_d2[111:0]};
			5'h0F:		sopData <= {din_d2[7:0]  ,din_d2[119:0]}; 
			//5'h10:		sopData <= {din_d2[127:0]};      					
			default:	sopData <= din_d2[127:0];
			endcase
		end
end

//din will be delay because sop will be change and sop_pos is built on sop.
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			dD1 <= 256'h0;
		//else if((sop_eop==1'h1 && no_eop==1'h0)  || sop_full==1'h1)//sop_eop
		//else if(sop_eop==1'h1 && double_sop==1'h0)
		else if(sop_eop==1'h1 && double_eop==1'h0)
		begin
			case({{~remainT[4]},sop_pos[3:0]})
			5'h00:		dD1[255:248]  <= din_d2[7:0];
			5'h01:		dD1[255:240]  <= din_d2[15:0];
			5'h02:		dD1[255:232]  <= din_d2[23:0];
			5'h03:		dD1[255:224] <= din_d2[31:0];
			5'h04:		dD1[255:216] <= din_d2[39:0];
			5'h05:		dD1[255:208] <= din_d2[47:0];
			5'h06:		dD1[255:200] <= din_d2[55:0];
			5'h07:		dD1[255:192] <= din_d2[63:0];
			5'h08:		dD1[255:184] <= din_d2[71:0];
			5'h09:		dD1[255:176] <= din_d2[79:0];
			5'h0A:		dD1[255:168] <= din_d2[87:0];
			5'h0B:		dD1[255:160] <= din_d2[95:0];
			5'h0C:		dD1[255:152] <= din_d2[103:0];
			5'h0D:		dD1[255:144] <= din_d2[111:0];
			5'h0E:		dD1[255:136] <= din_d2[119:0];
			5'h0F:		dD1[255:128] <= din_d2[127:0];
			
			5'h10:		dD1[127:120]<= din_d2[7:0];
			5'h11:		dD1[127:112]<= din_d2[15:0];
			5'h12:		dD1[127:104]<= din_d2[23:0];
			5'h13:		dD1[127:96] <= din_d2[31:0];
			5'h14:		dD1[127:88] <= din_d2[39:0];
			5'h15:		dD1[127:80] <= din_d2[47:0];
			5'h16:		dD1[127:72] <= din_d2[55:0];
			5'h17:		dD1[127:64] <= din_d2[63:0];
			5'h18:		dD1[127:56] <= din_d2[71:0];
			5'h19:		dD1[127:48] <= din_d2[79:0];
			5'h1A:		dD1[127:40] <= din_d2[87:0];
			5'h1B:		dD1[127:32] <= din_d2[95:0];
			5'h1C:		dD1[127:24] <= din_d2[103:0];
			5'h1D:		dD1[127:16] <= din_d2[111:0];
			5'h1E:		dD1[127:8] <= din_d2[119:0];
			default:	dD1[127:0] <= din_d2[127:0];
			endcase
		end
		else if(dval_d1==1'h1 || no_eop==1'h0)//|| no_sop==1'h0
		begin
			case(remain)
    	5'h00:		dD1 <= {din_d2[127:0],sopData[127:0]};
    	5'h01:		dD1 <= {sopData[7:0],  din_d2,sopData[127:8]  };
    	5'h02:		dD1 <= {sopData[15:0], din_d2,sopData[127:16] };
    	5'h03:		dD1 <= {sopData[23:0], din_d2,sopData[127:24] };
    	5'h04:		dD1 <= {sopData[31:0], din_d2,sopData[127:32] };
    	5'h05:		dD1 <= {sopData[39:0], din_d2,sopData[127:40] };
    	5'h06:		dD1 <= {sopData[47:0], din_d2,sopData[127:48] };
    	5'h07:		dD1 <= {sopData[55:0], din_d2,sopData[127:56] };
    	5'h08:		dD1 <= {sopData[63:0], din_d2,sopData[127:64] };
    	5'h09:		dD1 <= {sopData[71:0], din_d2,sopData[127:72] };
    	5'h0A:		dD1 <= {sopData[79:0], din_d2,sopData[127:80] };
    	5'h0B:		dD1 <= {sopData[87:0], din_d2,sopData[127:88] };
    	5'h0C:		dD1 <= {sopData[95:0], din_d2,sopData[127:96] };
    	5'h0D:		dD1 <= {sopData[103:0],din_d2,sopData[127:104]};
    	5'h0E:		dD1 <= {sopData[111:0],din_d2,sopData[127:112]};
    	5'h0F:		dD1 <= {sopData[119:0],din_d2,sopData[127:120]};
    	5'h10:		dD1 <= {sopData[127:0],din_d2[127:0]};
    	5'h11:		dD1 <= {din_d2[7:0],  sopData,din_d2[127:8]  };
    	5'h12:		dD1 <= {din_d2[15:0], sopData,din_d2[127:16] };
    	5'h13:		dD1 <= {din_d2[23:0], sopData,din_d2[127:24] };
    	5'h14:		dD1 <= {din_d2[31:0], sopData,din_d2[127:32] };
    	5'h15:		dD1 <= {din_d2[39:0], sopData,din_d2[127:40] };
    	5'h16:		dD1 <= {din_d2[47:0], sopData,din_d2[127:48] };
    	5'h17:		dD1 <= {din_d2[55:0], sopData,din_d2[127:56] };
    	5'h18:		dD1 <= {din_d2[63:0], sopData,din_d2[127:64] };
    	5'h19:		dD1 <= {din_d2[71:0], sopData,din_d2[127:72] };
    	5'h1A:		dD1 <= {din_d2[79:0], sopData,din_d2[127:80] };
    	5'h1B:		dD1 <= {din_d2[87:0], sopData,din_d2[127:88] };
    	5'h1C:		dD1 <= {din_d2[95:0], sopData,din_d2[127:96] };
    	5'h1D:		dD1 <= {din_d2[103:0],sopData,din_d2[127:104]};
    	5'h1E:		dD1 <= {din_d2[111:0],sopData,din_d2[127:112]};
    	5'h1F:		dD1 <= {din_d2[119:0],sopData,din_d2[127:120]};
    	default:	dD1 <= {sopData,din_d2};
    	endcase
		end
end

//sop_d2
always @(posedge clk or `RST_EDGE rst)//modify
begin
		if(rst == `RST_VALUE)
			sop_d2 <= 1'h0;	
		else if(hold_delay_d2==1'h0)//sop_eop
			sop_d2 <= 1'h0;	
		else if((sop_eop==1'h1 && no_eop==1'h0) || sop_full==1'h1)//sop_eop
			sop_d2 <= 1'h1;
		else if(sop_hold_d1==1'h1 && overflow_d2==1'h0)//sop hold, after overflow is eop
			sop_d2 <= 1'h1;		
		else if(no_sop==1'h0 && double_sop==1'h0 && sop_hold==1'h1)//sop delay,sop hold
			sop_d2 <= 1'h0;
		//else if(no_sop==1'h0 && sop_eop==1'h1)//normal
		//	sop_d2 <= 1'h1;
		else// if(sop_d2==1'h1 && val==1'h1)
			sop_d2 <= 1'h0;
end

//eop_d2
always @(posedge clk or `RST_EDGE rst)//delay
begin
		if(rst == `RST_VALUE)
			eop_d2 <= 1'h0;
		else if(eop_d1>16'h0 && overflow_d1>1'h0)
			eop_d2 <= 1'h0;
		else if(eop_d1>16'h0 || overflow_d2==1'h1)
			eop_d2 <= 1'h1;
		else
			eop_d2 <= 1'h0;
end

//pre_err
always @(posedge clk or `RST_EDGE rst)//delay
begin
		if(rst == `RST_VALUE)
			pre_err <= 1'h0;
		else if(discard_d1>16'h0 && overflow_d1>1'h0)
			pre_err <= 1'h0;
		else if(discard_d2>16'h0 && overflow_d2==1'h1)
			pre_err <= 1'h1;
		else if(discard_d1>16'h0)
			pre_err <= 1'h1;
		else
			pre_err <= 1'h0;
end
////////// third end ////////////////////////////////////

//forth
//snk_sop
always @(posedge clk or `RST_EDGE rst)//delay
begin
		if(rst == `RST_VALUE)
			snk_sop <= 1'h0;
		else if(val==1'h1)
			snk_sop <= sop_d2;
		else
			snk_sop <= 1'h0;
end

//snk_eop
always @(posedge clk or `RST_EDGE rst)//delay
begin
		if(rst == `RST_VALUE)
			snk_eop <= 1'h0;
		else if(val==1'h1)
			snk_eop <= eop_d2;
		else
			snk_eop <= 1'h0;
end

//snk_val
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			snk_val <= 1'h0;
		else
			snk_val <= val;
end

//snk_err
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			snk_err <= 1'h0;
		else
			snk_err <= pre_err;
end

//snk_mod
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			snk_mod <= 4'h0;
		else if(overflow_d3==1)
			snk_mod <= snk_mod;
		else //if(overflow_d1==0)
			snk_mod <= pre_mod[3:0];
end

//data out
always @(posedge clk or `RST_EDGE rst)
begin
		if(rst == `RST_VALUE)
			start <= 1'h0;
		else if(overflow_d2==1'h1)
			start <= ~start;
		else if(sop_d1==16'h8000 && eop_d1==16'h0)//
			start <= (~remainT[4]);
		else if(eop_d1>16'h0 && sop_d1>eop_d1)//
			start <= (~remainT[4]);//
		else 
			start <= remain[4];
end

always @(posedge clk or `RST_EDGE rst)
begin
    if(rst == `RST_VALUE)
    	snk_data <= 128'h0;
		else if(val>1'h0)
		begin
			case(start)
			1'h1:				snk_data[127:0] <= dD1[127:0];
    	default:		snk_data[127:0] <= dD1[255:128];
    	endcase
		end
end

endmodule 
